package com.webchat.pgc.service.mall;


import com.webchat.common.bean.APIPageResponseBean;
import com.webchat.common.constants.MallConstants;
import com.webchat.common.enums.RedisKeyEnum;
import com.webchat.common.enums.mall.MallReviewStatusEnum;
import com.webchat.common.enums.mall.MallStatusEnum;
import com.webchat.common.service.RedisService;
import com.webchat.common.util.JsonUtil;
import com.webchat.domain.vo.request.mall.ShopSubmitRequestVO;
import com.webchat.domain.vo.response.mall.MallShopBaseVO;
import com.webchat.domain.vo.response.mall.MallShopResponseVO;
import com.webchat.pgc.repository.dao.mall.IMallShopDAO;
import com.webchat.pgc.repository.entity.mall.MallShop;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class MallShopService {

    @Autowired
    private IMallShopDAO mallShopDAO;

    @Autowired
    private RedisService redisService;

    @Autowired
    private MallShopReviewService mallShopReviewService;


    /**
     * 申请开店
     *
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Long submit(ShopSubmitRequestVO requestVO) {
        // 1. 保存或者更新店铺
        MallShop shop = this.convert(requestVO);
        shop = mallShopDAO.save(shop);
        Long shopId = shop.getId();
        // 2. 提交审核信息
        mallShopReviewService.create(shop, requestVO.getOperator());
        // 3. 刷新店铺缓存
        this.refreshCache(shop);
        this.refreshUserShopCache(requestVO.getOperator(), shopId);
        return shopId;
    }

    /**
     * 查询账号下的店铺信息
     *
     * @param userId
     * @return
     */
    public MallShopBaseVO manageShopInfo(String userId) {

        Long shopId = getUserShopId(userId);
        if (shopId == null) {
            return null;
        }
        return detail(shopId);
    }

    /**
     * 更新审核结果，更新店铺状态
     *
     * @param shopId
     * @param reviewStatusEnum
     * @return
     */
    public boolean updateStatusByReview(Long shopId, MallReviewStatusEnum reviewStatusEnum) {
        Date now = new Date();
        MallShop shop = this.get(shopId);
        Assert.notNull(shop, "店铺不存在");
        MallStatusEnum mallStatus = MallStatusEnum.getByReviewStatus(reviewStatusEnum);
        shop.setStatus(mallStatus.getStatus());
        shop.setUpdateDate(now);
        // 首次审核通过时间（店铺入驻时间）
        if (reviewStatusEnum == MallReviewStatusEnum.APPROVED && shop.getReviewDate() == null) {
            shop.setReviewDate(now);
        }
        mallShopDAO.save(shop);
        // 刷新店铺缓存
        refreshCache(shop);
        return true;
    }

    /**
     * 店铺撤回
     *
     * @return
     */
    public boolean invoke(Long shopId, String operator) {

        // TODO 店铺操作校验

        MallShop shop = mallShopDAO.findById(shopId).orElse(null);
        Assert.notNull(shop, "线下失败：店铺信息不存在");
        shop.setStatus(MallStatusEnum.UNPUBLISHED.getStatus());
        shop.setUpdateBy(operator);
        shop.setUpdateDate(new Date());
        mallShopDAO.save(shop);
        refreshCache(shop);
        return false;
    }

    /**
     * 店铺删除
     *
     * @return
     */
    public boolean delete(Long shopId, String operator) {

        // TODO
        MallShop shop = mallShopDAO.findById(shopId).orElse(null);
        Assert.notNull(shop, "删除失败：店铺信息不存在");
        shop.setStatus(MallStatusEnum.DELETED.getStatus());
        shop.setUpdateBy(operator);
        shop.setUpdateDate(new Date());
        mallShopDAO.save(shop);
        refreshCache(shop);
        return false;
    }

    /**
     * 管理端详情查询
     *
     * @return
     */
    public Object detailForBackend() {

        // TODO
        return null;
    }

    /**
     * 用户端店铺详情信息
     *
     * @return
     */
    public MallShopBaseVO baseDetail(Long shopId) {
        String key = RedisKeyEnum.MALL_SHOP_BASE_CACHE.getKey();
        String cache = redisService.hget(key, String.valueOf(shopId));
        if (StringUtils.isBlank(cache)) {
            // 刷新店铺缓存
            return this.refreshCache(shopId);
        }
        return JsonUtil.fromJson(cache, MallShopBaseVO.class);
    }

    public MallShopResponseVO detail(Long shopId) {
        MallShopBaseVO shopBase = this.baseDetail(shopId);
        if (shopBase == null) {
            return null;
        }
        MallShopResponseVO shopDetail = new MallShopResponseVO();
        BeanUtils.copyProperties(shopBase, shopDetail);
        // TODO 取店铺扩展信息：评分、平均回复时间……
        return shopDetail;
    }

    /**
     * 批量查询店铺信息（缓存）
     *
     * @return
     */
    public List<MallShopBaseVO> batchGetList(List<Long> shopIds) {

        if (CollectionUtils.isEmpty(shopIds)) {
            return Collections.emptyList();
        }
        String key = RedisKeyEnum.MALL_SHOP_BASE_CACHE.getKey();
        List<String> shopIdKeys = shopIds.stream().map(String::valueOf).toList();
        List<String> caches = redisService.hmget(key, shopIdKeys);
        List<MallShopBaseVO> list = new ArrayList<>();
        for (int i = 0; i < shopIds.size(); i++) {
            Long shopId = shopIds.get(i);
            String cache = caches.get(i);
            MallShopBaseVO shopBase;
            if (StringUtils.isNotBlank(cache)) {
                shopBase = JsonUtil.fromJson(cache, MallShopBaseVO.class);
            } else {
                shopBase = baseDetail(shopId);
            }
            list.add(shopBase);
        }
        return list;
    }

    /**
     *
     * @return
     */
    public Map<Long, MallShopBaseVO> batchGetMap(List<Long> shopIds) {
        List<MallShopBaseVO> shops = this.batchGetList(shopIds);
        if (CollectionUtils.isEmpty(shops)) {
            return Collections.emptyMap();
        }
        return shops.stream().collect(
                Collectors.toMap(MallShopBaseVO::getId, s -> s, (k1, k2) -> k2));
    }

    /**
     * 刷新店铺信息缓存
     *
     * @return
     */
    public MallShopBaseVO refreshCache(Long shopId) {

        MallShop shop = mallShopDAO.findById(shopId).orElse(null);
        return this.refreshCache(shop);
    }

    public MallShopBaseVO refreshCache(MallShop shop) {
        if (shop == null) {
            return null;
        }
        String key = RedisKeyEnum.MALL_SHOP_BASE_CACHE.getKey();
        MallShopBaseVO shopBaseVO = this.convert(shop);
        redisService.hset(key, String.valueOf(shop.getId()), JsonUtil.toJsonString(shopBaseVO),
                          RedisKeyEnum.MALL_SHOP_BASE_CACHE.getExpireTime());
        return shopBaseVO;
    }

    public Long getUserShopId(String userId) {
        String key = RedisKeyEnum.MALL_USER_SHOP_ID_CACHE.getKey();
        String shopIdCache = redisService.hget(key, userId);
        if (StringUtils.isNotBlank(shopIdCache)) {
            return Long.valueOf(shopIdCache);
        }
        return refreshUserShopCache(userId);
    }

    public void refreshUserShopCache(String userId, Long shopId) {
        if (StringUtils.isBlank(userId) || shopId == null) {
            return;
        }
        String key = RedisKeyEnum.MALL_USER_SHOP_ID_CACHE.getKey();
        redisService.hset(key, userId, String.valueOf(shopId),
                RedisKeyEnum.MALL_USER_SHOP_ID_CACHE.getExpireTime());
    }

    public Long refreshUserShopCache(String userId) {
        List<MallShop> shops = mallShopDAO.findAllByCreateBy(userId);
        if (CollectionUtils.isEmpty(shops)) {
            return null;
        }
        MallShop shop = shops.get(shops.size() - 1);
        this.refreshUserShopCache(userId, shop.getId());
        return shop.getId();
    }

    /**
     * 管理端列表查询
     *
     * @return
     */
    public APIPageResponseBean<Object> pageList() {

        return null;
    }


    private MallShop get(Long shopId) {
        return mallShopDAO.findById(shopId).orElse(null);
    }

    private MallShop convert(ShopSubmitRequestVO requestVO) {

        String operator = requestVO.getOperator();
        Long id = requestVO.getId();
        Date now = new Date();
        MallShop mallShop;
        if (id != null) {
            mallShop = mallShopDAO.findById(id).orElse(null);
            Assert.notNull(mallShop, "店铺不存在");
        } else {
            mallShop = new MallShop();
            mallShop.setCreateBy(operator);
            mallShop.setCreateDate(now);
            mallShop.setStatus(MallStatusEnum.NEW.getStatus());
        }
        mallShop.setName(requestVO.getName());
        mallShop.setLogo(requestVO.getLogo());
        mallShop.setUpdateBy(operator);
        mallShop.setUpdateDate(now);
        return mallShop;
    }

    private MallShopBaseVO convert(MallShop shop) {
        if (shop == null) {
            return null;
        }
        MallShopBaseVO mallShopBaseVO = new MallShopBaseVO();
        BeanUtils.copyProperties(shop, mallShopBaseVO);
        Date firstReviewDate;
        if ((firstReviewDate = shop.getReviewDate()) != null) {
            mallShopBaseVO.setReviewTime(firstReviewDate.getTime());
        }
        return mallShopBaseVO;
    }
}
